#include "test_dll.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <mm/early_alloc.h>
#include <mm/pages.h>
#include <mm/page_alloc.h>
#include <mm/compound_pages.h>
#include <mm/physical_area.h>
#include <mm/memory.h>
#include <mm/slab.h>
#include <mm/kmalloc.h>

/// 分配16MB
#define V_MEM_SIZE  (16UL << 20)

#define V_PAGE_ORDER 12

static void *v_mem = NULL;

unsigned long get_virtual_base(void)
{
    return (unsigned long)v_mem;
}

int init_test_dll(void)
{
    /// 分配测试用的内存区域。
    v_mem = aligned_alloc(V_MEM_SIZE, V_MEM_SIZE);
    if (v_mem != NULL) {
        memset(v_mem, 0, V_MEM_SIZE);
    }
    unsigned long page_start = (VIRT_TO_PHY(v_mem) >> 12);
    unsigned long page_end = page_start + (V_MEM_SIZE >> 12);
    
    printf("%lu %lu\n", page_start, page_end);
    /// 初始化前期内存分配器。
    if (early_alloc_init(page_start, page_end, page_start, page_end, 12)) {
        return -1;
    }

    if (pages_init(VIRT_TO_PHY(v_mem), VIRT_TO_PHY(v_mem) + V_MEM_SIZE, 0)) {
        return -2;
    }
    
    if (set_pages_valid(VIRT_TO_PHY(v_mem), VIRT_TO_PHY(v_mem) + V_MEM_SIZE)) {
        return -3;
    }

    /// 添加内存区域。
    if (add_physical_area(VIRT_TO_PHY(v_mem), (6UL << 20))) {
        return -4;
    }
    
    if (add_physical_area(VIRT_TO_PHY(v_mem) + (6UL << 20), (2UL << 20))) {
        return -5;
    }

    /// 初始化pglist
    if (pglist_init(1)) {
        return -6;
    }

    /// 初始化内存区域结构体。
    if (mem_zones_init()) {
        return -7;
    }

    /// 激活伙伴系统。
    if (activate_buddy_system()) {
        return -8;
    }

    /// 初始化 Slab 分配器。
    if (kmalloc_init()) {
        return -9;
    }


    return 0;
}

/**
 * @brief 退出测试用户管理系统。
 */
void exit_test_dll(void)
{
    free(v_mem);
}
